function __keyActionHandler(flag) {
  return function(e) {
    const code = e.code.toLowerCase().replace('key', '');
    // 字母按键的code是keya, keyb这种形式的，替换掉key就能得到键所代表的字母了
    if(['a','s','d','w'].includes(code)) {
      let direction = {
        a: 'left',
        s: 'down',
        d: 'right',
        w: 'up'
      }[code]
      this.direction[direction] = flag;
      this.angle = PLAYER_DIRECTION[Object.values(this.direction).map(o=>+o).join('')]
    }else if(code === 'k') {
      this.isOnFire = flag
    }
  }
}
class Player extends Moveable{
  constructor({name, x, y, width, height, game, hp, speed}) {
    super({name, type: MOB_TYPES.PLAYER, x, y, width, height, game, hp, speed})
    this.lifeTick = 0;
    this.fireTick = 0;
    this.activeEngine = null;
    this.direction = {
      up: false,
      down: false,
      left: false,
      right: false
    }
    this.isOnFire = false
    this[KEY_DOWN_HANDLER] = __keyActionHandler(true).bind(this)
    this[KEY_UP_HANDLER] = __keyActionHandler(false).bind(this)
    window.addEventListener('keydown', this[KEY_DOWN_HANDLER]);
    window.addEventListener('keyup', this[KEY_UP_HANDLER]);
    this.activeEngine = setInterval(() => {
      // 有角度就按角度移动
      if(typeof this.angle !== 'undefined'){
        let {x: targetX, y: targetY} = this.preMove(speed)
        this.move(targetX, targetY);
      }
      // 按下发射按钮的时候按固定时间间隔发射子弹
      let tick = Date.now();
      if(this.isOnFire && (!this.fireTick || tick - this.fireTick > 200)){
        // 创建一个投射物（和怪物发射子弹类似）
        let projectile = new Projectile({
          name: 'bullet',
          type: MOB_TYPES.BULLET,
          x: this.x + this.width,
          y: this.y + 20,
          width: 20, 
          height: 20,
          game: this.game,
          hp: 20,
          speed: this.speed * 1.5,
          angle: 0
        })
        projectile.on('move', ({x, y}) => {
          // 向game派发子弹移动事件，交由外部统一处理
          // 注意：这里的this是player
          this.emit('bulletMove', projectile)
        })
        .on('outSide', () => {
          // 当子弹移出画面外时销毁掉
          projectile.release();
          this.removeProjectile(projectile);
        })
        this.projectiles.push(projectile)
        this.fireTick = tick;
      }
    }, 10)
  }
  get hp() {
    return this.hits
  }
  set hp(hp) {
    if(hp < this.hits) {
      let tick = Date.now();
      if(!this.lifeTick || tick - this.lifeTick > 500){
        this.emit('harmed', hp);
        this.lifeTick = tick;
      }else {
        return
      }
    }
    if(hp < 0) {
      hp = 0;
    }
    this.hits = hp;
    if(!this.hp) {
      this.emit('dead', this.hp)
      this.release();
    }
  }
  get hpPercent() {
    return Math.round(this.hits/this.hits_max * 100)
  }
  release() {
    clearInterval(this.activeEngine);
    this.activeEngine = null;
    super.release();
    window.removeEventListener('keydown', this[KEY_DOWN_HANDLER]);
    window.removeEventListener('keyup', this[KEY_UP_HANDLER]);
  }
}

